<template>
  <div>
    <video ref="videoElement" controls width="100%" autoplay>浏览器不支持播放视频</video>
  </div>
</template>

<script>
import { loadRemote } from '@vimi/utils-tool'

const streamIp = '119.1.219.25'
const wsApi = `ws://${streamIp}:8000/api/stream/ws`
const streamHost = `http://${streamIp}:8081`
const flvJs = 'https://cdn.bootcdn.net/ajax/libs/flv.js/1.5.0/flv.min.js'

export default {
  components: {},
  props: {
    deviceId: String,
  },
  data() {
    return {
      loading: false,
      loadingStream: false,
      flvPlayer: null,
      ws: null,
      beatTimer: null,
    }
  },
  computed: {},
  watch: {
    deviceId: {
      handler: function () {
        this.getVideoPlayUrl()
      },
      immediate: true,
    },
  },
  created() {},
  mounted() {},
  methods: {
    getVideoPlayUrl() {
      if (!this.deviceId || this.loading || this.loadingStream) {
        return
      }

      this.loading = true
      loadRemote(flvJs, 'flvjs')
        .then(() => {
          if (!window.flvjs.isSupported()) {
            return Promise.reject(new Error('浏览器不支持播放该视频'))
          }
          this.loading = false
          return this.wsPlay()
        })
        .catch(() => {
          this.loading = false
          this.$message.error('视频播放失败')
        })
    },
    wsPlay() {
      this.destroy()
      this.loading = true

      const wsUrl = `${wsApi}?deviceId=${this.deviceId}`
      this.ws = new WebSocket(wsUrl)
      this.ws.addEventListener('open', () => {
        this.loading = false
        console.log('连接成功，等待播放') // eslint-disable-line no-console
      })
      this.ws.addEventListener('message', r => {
        this.messageHandler(r)
      })
      this.ws.addEventListener('close', () => {
        // this.$message.error('播放关闭')
        this.destroy()
      })
      this.ws.addEventListener('error', () => {
        this.$message.error('播放出错')
        this.destroy()
      })
    },
    messageHandler(r) {
      try {
        const parse = JSON.parse(r.data) || {}
        const { code, data, msg } = parse
        if (code === 0) {
          const { type, path } = data
          // 0-拉流成功 1-流媒体服务器推流成功
          if (type === 1) {
            if (!this.flvPlayer) {
              const playUrl = `${streamHost}${path}.flv`
              this.playFlv(playUrl)
              this.heartBeat()
            }
            this.loadingStream = false
          } else {
            // 返回地址，但流媒体服务器可能还没推流完成
            this.loadingStream = true
          }
        } else {
          this.$message.error(msg || '播放视频失败')
          this.destroy()
        }
      } catch (error) {
        console.error(error) // eslint-disable-line no-console
      }
    },
    heartBeat() {
      clearInterval(this.beatTimer)
      this.beatTimer = setInterval(() => {
        if (this.ws && this.flvPlayer) {
          this.ws.send('{}')
        }
      }, 50000)
    },
    playFlv(url) {
      this.loading = false
      this.flvPlayer = window.flvjs.createPlayer({
        type: 'flv',
        isLive: true,
        hasAudio: true,
        hasVideo: true,
        enableStashBuffer: true,
        url,
      })
      this.flvPlayer.attachMediaElement(this.$refs.videoElement)
      this.flvPlayer.load()
      this.flvPlayer.play()
      this.flvPlayer.on(window.flvjs.Events.ERROR, () => {
        this.destroy()
      })
    },
    destroy() {
      clearInterval(this.beatTimer)
      this.loading = false
      if (this.ws) {
        this.ws.close()
        this.ws = null
      }
      if (this.flvPlayer) {
        this.flvPlayer.pause()
        this.flvPlayer.unload()
        this.flvPlayer.detachMediaElement()
        this.flvPlayer.destroy()
        this.flvPlayer = null
      }
    },
  },
  beforeDestroy() {
    this.destroy()
  },
}
</script>

<style lang="scss" scoped></style>
